from pathlib import Path
import tkinter as tk
import customtkinter as ctk
from ctkutils import PdfShow, FloatSpinbox, CTkListbox
from pdfUtils import PdfUtil


class PdfToolUi(ctk.CTk):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setupUi()
        self.pdfFiles = list()
        self.needDels = list()
        self.bind('<<CHKCLICK-1>>', self.checkToggle_1, add='+')
        self.bind('<<CHKCLICK-0>>', self.checkToggle_0, add='+')
        self.bind('<<ADDPAGE>>', self.prevPage,add='+')
        self.bind('<<SUBPAGE>>', self.nextPage,add='+')
        self.splitPageNums = list()
        self.needSplitFile = None

    def prevPage(self, event):
        pgn = self.pageSpb.get()
        self.currentPage = self.pdff.getPageImg(pgn)
        self.imageLb.configure(image=self.currentPage)

    def nextPage(self, event):
        pgn = self.pageSpb.get()
        self.currentPage = self.pdff.getPageImg(pgn)
        self.imageLb.configure(image=self.currentPage)

    def checkToggle_1(self, event):
        self.needDels.append(event.widget.id)

    def checkToggle_0(self, event):
        try:
            self.needDels.remove(event.widget.id)
        except Exception as e:
            pass

    def setupUi(self):
        # 窗口主题
        ctk.set_appearance_mode('Dark')
        ctk.set_default_color_theme('green')
        self.title('PDF工具')  
        self.geometry('1024x768')
        self.resizable(0,0)

        self.grid_columnconfigure(0,weight=1)
        self.grid_rowconfigure(0,weight=1)

        self.main_frame = ctk.CTkFrame(self)
        self.main_frame.grid(row=0, column=0, sticky='news')

        self.main_frame.grid_columnconfigure(0,weight=1)
        self.main_frame.grid_rowconfigure(0,weight=1)

        self.ptabview = ctk.CTkTabview(self.main_frame )
        self.ptabview.grid(row=0, column=0, sticky='news', padx=20, pady=(10,20))
        self.ptabview.add('合并')
        self.ptabview.add('分割')

        # 合并选项页
        self.ptabview.tab('合并').grid_columnconfigure((0, 1, 2), weight=1)
        self.ptabview.tab('合并').grid_rowconfigure(0,weight=1)
        self.ptabview.tab('合并').grid_rowconfigure(1,weight=29)

        self.addBtnInMergePage = ctk.CTkButton(self.ptabview.tab('合并') ,text='添加')
        self.addBtnInMergePage.configure(command = self.addBtnInMergePageClick)
        self.addBtnInMergePage.grid(row=0, column=0, pady =(10, 10), padx=10)
        self.delBtnInMergePage = ctk.CTkButton(self.ptabview.tab('合并') ,text='删除')
        self.delBtnInMergePage.configure(command = self.delBtnInMergePageClick)
        self.delBtnInMergePage.grid(row=0, column=1, pady =(10, 10), padx=10)
        self.mergeBtnInMergePage = ctk.CTkButton(self.ptabview.tab('合并') ,text='合并')
        self.mergeBtnInMergePage.configure(command=self.mergeBtnInMergePageClick)
        self.mergeBtnInMergePage.configure(command=self.mergeBtnInMergePageClick)
        self.mergeBtnInMergePage.grid(row=0, column=2, pady =(10, 10), padx=10)

        self.scrollFrameMerge = ctk.CTkScrollableFrame(self.ptabview.tab('合并'))
        self.scrollFrameMerge.grid_columnconfigure((0, 1, 2, 3), weight=1, minsize=230)
        self.scrollFrameMerge.grid(row=1, column=0, columnspan=3, sticky='news')
        # 分割选项面的页面布局
        self.ptabview.tab('分割').columnconfigure(0, weight=9)
        self.ptabview.tab('分割').columnconfigure(1, weight=1)
        self.ptabview.tab('分割').rowconfigure(0, weight=10)
        # 左侧文件显示区域
        # self.splitPageShowFram = ctk.CTkScrollableFrame(self.ptabview.tab('分割'))
        self.splitPageShowFram = ctk.CTkFrame(self.ptabview.tab('分割'))
        self.splitPageShowFram.rowconfigure((0, 3), weight=1)
        self.splitPageShowFram.rowconfigure(1, weight=50)
        self.splitPageShowFram.columnconfigure(0, weight=10)
        self.splitPageShowFram.grid(row=0, column=0, sticky='news', padx=10, pady=10)
        self.openFileBtnInSplitPage = ctk.CTkButton(self.splitPageShowFram,text='打开要分割的PDF文件')
        self.pdfShowFram = ctk.CTkScrollableFrame(self.splitPageShowFram)
        self.openFileBtnInSplitPage.configure(command=self.openFileBtnInSplitPageClick)
        self.openFileBtnInSplitPage.grid(row=0, column=0, sticky='news', padx=10, pady=10)
        self.pdfShowFram.grid(row=1, column=0, sticky='news', padx=10, pady=10)
        self.pageSpb = FloatSpinbox(self.splitPageShowFram)
        self.pageSpb.name = 10
        self.pageSpb.grid(row=2, column=0, sticky='news', padx=10, pady=10)
        # self.showCanv = ctk.CTkCanvas(self.splitPageShowFram)
        # self.showCanv.grid(row=0, column=0, sticky='news')

        # 右侧分割选项区域
        self.splitPageConfigFram = ctk.CTkScrollableFrame(self.ptabview.tab('分割'))
        self.splitPageConfigFram.grid(row=0, column=1,  sticky='news', padx=10, pady=10)
        self.splitPageConfigFram.grid_columnconfigure(0, weight=2)
        self.splitPageConfigFram.grid_columnconfigure(1, weight=4)
        self.splitPageConfigFram.grid_rowconfigure((0, 1, 2, 3), weight=1)
        self.splitPageConfigFram.grid_rowconfigure(4, weight=9)
        self.perPageSplitBtn = ctk.CTkButton(self.splitPageConfigFram, text='分隔为单页文件')
        self.perPageSplitBtn.configure(command=self.saveSplitDir)
        self.perPageSplitBtn.grid(row=0, column=0, columnspan=2, sticky='news', padx=10, pady=10)
        self.startPageLb = ctk.CTkLabel(self.splitPageConfigFram, text='起始页')
        self.startPageSpb = FloatSpinbox(self.splitPageConfigFram)
        self.endPageLb = ctk.CTkLabel(self.splitPageConfigFram, text='终止页')
        self.endPageSpb = FloatSpinbox(self.splitPageConfigFram)
        self.startPageLb.grid(row=1, column=0, padx=0, pady=5 )
        self.startPageSpb.grid(row=1, column=1, padx=5, pady=5, sticky='wns')
        self.endPageLb.grid(row=2, column=0, padx=5, pady=5)
        self.endPageSpb.grid(row=2, column=1, padx=5, pady=5, sticky='wns')
        self.addRangeBtn = ctk.CTkButton(self.splitPageConfigFram, text='+')
        self.addRangeBtn.configure(command=self.addRangebtnClick)
        self.addRangeBtn.grid(row=3,column=0, padx=5, pady=5, columnspan=2)
        self.rangeListbox = CTkListbox(self.splitPageConfigFram, height=350)
        self.rangeListbox.grid(row=4, column=0, padx=5, pady=10, columnspan=2, sticky='news')
        self.delRangeBtn = ctk.CTkButton(self.splitPageConfigFram, text='删除分割范围')
        self.delRangeBtn.configure(command=self.delRangItem)
        self.delRangeBtn.grid(row=5, column=0, columnspan=2, padx=5, pady=10, sticky='news')
        self.splitRangeBtn = ctk.CTkButton(self.splitPageConfigFram, text='进行分割')
        self.splitRangeBtn.configure(command=self.splitRangeBtnClick)
        self.splitRangeBtn.grid(row=6, column=0, columnspan=2, padx=5, pady=10, sticky='news')
 
    # 按范围进行分割按钮回调函数
    def splitRangeBtnClick(self):
        if not self.rangeListbox.size():
            return
        if not self.needSplitFile:
            return
        dpath = tk.filedialog.askdirectory()
        if not dpath:
            return
        dpath = Path(dpath)
        nsf = Path(self.needSplitFile)
        fname = nsf.stem
        if dpath:
            pdff = PdfUtil(self.needSplitFile)
            ranges = [item.values() for item in self.splitPageNums]
            for item in ranges:
                for i in item:
                    _start = i[0]
                    _end = i[1]
                    _sname = f'{fname}第{_start}页至{_end}页.pdf'
                    _spath = dpath / _sname
                    try:
                        pdff.split(_spath, _start, _end)
                        print('成功')
                    except Exception as e:
                        print(e)

    # 分割单页文件保存路径
    def saveSplitDir(self):
        if self.needSplitFile:
            dpath = tk.filedialog.askdirectory()
            nsf = Path(self.needSplitFile)
            fname = nsf.stem
            if dpath:
                pdff = PdfUtil(self.needSplitFile)
                flag = pdff.splitPer(dpath)
                if flag['status']:
                    tk.messagebox.showinfo('提示', '文件分割成功')
                if not flag['status']:
                    err = flag['info']
                    tk.messagebox.showinfo('提示', f'分割失败,失败原因{err}')
                

    # 删除范围列表框中的项目
    def delRangItem(self):
        flag = None 
        if self.rangeListbox.size():
            if self.rangeListbox.curselection() is not None :
                info = self.rangeListbox.get(self.rangeListbox.curselection())
                self.rangeListbox.delete(self.rangeListbox.curselection())
                for i, item in enumerate(self.splitPageNums):
                    if info in item.keys():
                        flag = i
                del self.splitPageNums[flag]

    def addPdfShow(self, fname, rowNum, colNum):
        pdfShow = PdfShow(self.scrollFrameMerge)
        pdfShow.setFileName(fname)
        pdfShow.showFile()
        pdfShow.grid(row=rowNum, column=colNum, padx=10, pady=(10, 10) )

    def addPdfShowNew(self, fname):
        perRowNum = 4
        rowNum = 0
        colNum = 0
        fpath = Path(fname)
        displayName = fpath.stem
        pdfShow = PdfShow(self.scrollFrameMerge)
        self.pdfFiles.append(pdfShow)
        allFilesNum = len(self.pdfFiles)
        if allFilesNum <= perRowNum:
            rowNum = 0
            if allFilesNum == perRowNum:
                colNum = perRowNum - 1
            colNum = allFilesNum - 1
        else:
            if allFilesNum % perRowNum == 0:
                colNum = perRowNum - 1
                rowNum = allFilesNum // perRowNum -1
            else:
                colNum = allFilesNum % perRowNum - 1 
                rowNum = allFilesNum // perRowNum
        pdfShow.setFileName(fname)
        pdfShow.showFile()
        pdfShow.grid(row=rowNum, column=colNum, padx=10, pady=(10, 10) )

    # 添加按钮的单击事件响应
    def addBtnInMergePageClick(self):
        fname = ctk.filedialog.askopenfilename(title='选择文件', filetypes=[('PDF文件', '*.pdf'), ('全部文件', '*.*')])
        if fname:
            self.addPdfShowNew(fname)

    # 合并页面删除按钮的单击事件响应
    def delBtnInMergePageClick(self):
        for pf in self.pdfFiles:
            pf.destroy()
        for nd in self.needDels:
            for pf in self.pdfFiles:
                if pf.id == nd:
                    self.pdfFiles.remove(pf)
        pdfname = [p.fname for p in self.pdfFiles]
        self.pdfFiles = []
        for pf in pdfname:
            self.addPdfShowNew(pf)
        self.needDels = []

    # 合并按钮响应
    def mergeBtnInMergePageClick(self):
        info = ''
        if not len(self.pdfFiles):
            tk.messagebox.showinfo('信息', '没有要合并的文件')
            return
        fn = ctk.filedialog.asksaveasfile(title='保存文件', filetypes=[('PDF文件', '*.pdf'), ('全部文件', '*.*')])
        if fn:
            pdfobj = PdfUtil()
            flag = pdfobj.merge(self.pdfFiles,fn)
            if flag:
                info = '文件合并成功。'
            else:
                info = '文件合并失败。'
            tk.messagebox.showinfo('信息', info)

    # 打开要分割的PDF文件按钮响应函数
    def openFileBtnInSplitPageClick(self):
        # self.openFileBtnInSplitPage.destroy()
        fname = ctk.filedialog.askopenfilename(title='打开文件', filetypes=[('PDF文件', '*.pdf'), ('全部文件', '*.*')])
        if fname:
            self.needSplitFile = fname
            self.pdff = PdfUtil(fname)
            max = self.pdff.getMax()
            self.startPageSpb.setMax(max)
            self.endPageSpb.setMax(max)
            self.pageSpb.setMax(max)
            self.startPageSpb.set(1)
            self.endPageSpb.set(1)
            self.pageSpb.set(1)
            self.currentPage = self.pdff.getPageImg(1)
            self.imageLb = tk.Label(self.pdfShowFram, image=self.currentPage)
            self.imageLb.grid(row=1, column=0, padx=10, pady=10)
            


    # 选定范围后，添加选定范围按钮的响应函数
    def addRangebtnClick(self):
        start = self.startPageSpb.get()
        end = self.endPageSpb.get()
        if not self.needSplitFile:
            return
        if start > end:
            tk.messagebox.showinfo('提示', '起始页不能比终止页大')
            return
        info = f'第{start}页至第{end}页'
        contents = self.rangeListbox.get('all')
        if contents:
            if info in contents:
                return
        self.rangeListbox.insert('end', info)
        self.splitPageNums.append({info:(start, end)})

        

def main():
    app = PdfToolUi()
    app.mainloop()

if __name__ == "__main__":
    main()

